#include "dlist.h"

void dlist_init (DList *head)
{
    head->next = head;
    head->prev = head;
}

/*
 * insert new before node, and move head to the first node
 */
void dlist_insert_before (DList *node, DList *new, DList **head)
{
    new->next = node;
    new->prev = node->prev;

    node->prev->next = new;
    node->prev = new;

    if (node == *head)
    {
        *head = new;
    }
}

void dlist_insert_after (DList *node, DList *new)
{
    new->next = node->next;
    new->prev = node;

    node->next->prev = new;
    node->next = new;
}

void dlist_insert_tail (DList **head, DList *new_node)
{
    if (*head == NULL)
    {
        *head = new_node;
        (*head)->next = new_node;
        (*head)->prev = new_node;
    }
    else
    {
        DList *tail = (*head)->prev;
        dlist_insert_after (tail, new_node);
    }
}

void dlist_del (DList *node, DList **head)
{
    node->prev->next = node->next;
    node->next->prev = node->prev;

    if (*head == node)
    {
        *head = node->next;
    }
}

void dlist_move (DList *des, DList *src, DList **head, int before)
{
    dlist_del (src, head);
    if (before)
    {
        dlist_insert_before (des, src, head);
    }
    else
    {
        dlist_insert_after (des, src);
    }
}

void dlist_move_pre (DList *node, DList **head)
{
    if (node == *head)
    {
        return;
    }
    DList *prev_node = node->prev;

    dlist_move (prev_node, node, head, 1);
}

void dlist_move_next (DList *node, DList **head)
{
    if (node == (*head)->prev)
    {
        return;
    }
    DList *next_node = node->next;

    dlist_move (next_node, node, head, 0);
}

DList *dlist_next (DList *node)
{
    return node->next;
}

DList *dlist_prev (DList *node)
{
    return node->prev;
}

